/*
 * main.c
 *
 *  Created on: 14/09/2010
 *      Author: dela
 */

#include "domain/film.h"
#include "domain/person.h"
#include "domain/node.h"
#include "business/parser.h"
#include "business/listaAux.h"
#include "business/preprocessor.h"
#include "fileSystem/matrix_mem.h"
#include "fileSystem/fileStructs.h"
#include "fileSystem/file.h"
#include <malloc.h>
#include <string.h>
#include <time.h>

/**
 *
 */
void parserTest() {
	int contFilmsTotal = 0;
	int contPersonsTotal = 0;
	int i = 0;
	char *fileName = malloc( 25*sizeof(char) );
	sprintf(fileName,"DataSet/data-%i.xml",i);
	FILE *file = fopen( fileName, "r" );
	while (file) {
		//printf("Archivo abierto.\n\n\n");
		printf("%s",fileName);

		int contFilms = 0;
		int contPersons = 0;
		TFilm *film;
		film = malloc( sizeof(TFilm) );
		TPerson *person;
		while ( parser_getNextFilm(file, film) ) {
//			printf( "[Pelicula]%s\n", film->title );
			if ( !ls_Vacia( film->people ) ) {
				ls_MoverCorriente( &(film->people), LS_PRIMERO );
				do {
					ls_ElemCorriente( film->people, (void**)&person );
					contPersons++;
					printf( "  [Persona]%s\n", person->name );
				} while ( ls_MoverCorriente( &(film->people), LS_SIGUIENTE ) );
			}
			film_destroy(film);
//			printf("\n");
			contFilms++;
		}
		contFilmsTotal = contFilmsTotal +contFilms;
		contPersonsTotal = contPersonsTotal + contPersons;
		free(film);
		printf("\nCantidad de peliculas: %i\n", contFilms);
		printf("Cantidad de personas: %i\n", contPersons);
		printf("\n");

		fclose(file);

		i++;
		sprintf(fileName,"DataSet/data-%i.xml",i);
		file = fopen( fileName, "r" );
	}
	free(fileName);

	printf("\n-------------------------------\n");
	printf("\nCantidad de peliculas total: %i\n", contFilmsTotal);
	printf("Cantidad de personas total: %i\n", contPersonsTotal);
	printf("\n");
}

void testListAux() {
	TListaSimple nombres;
	ls_Crear( &nombres );
	int i = 0;
	char *fileName = malloc( 25*sizeof(char) );
	sprintf(fileName,"DataSet/data-%i.xml",i);
	FILE *file = fopen( fileName, "r" );
	while (file) {
		printf("%s\n",fileName);
		TFilm *film;
		film = malloc( sizeof(TFilm) );
		TPerson *person;
		while ( parser_getNextFilm(file, film) ) {
			if ( !ls_Vacia( film->people ) ) {
				ls_MoverCorriente( &(film->people), LS_PRIMERO );
				do {
					ls_ElemCorriente( film->people, (void**)&person );
					char *name = malloc( (strlen(person->name)+1)*sizeof(char) );
					strcpy(name, person->name);
					if ( !lsAux_insertOrderString( &nombres, name ) ){
						free(name);
					}
				} while ( ls_MoverCorriente( &(film->people), LS_SIGUIENTE ) );
			}
			film_destroy(film);
		}
		free(film);

		fclose(file);

		i++;
		sprintf(fileName,"DataSet/data-%i.xml",i);
		file = fopen( fileName, "r" );
	}
	free(fileName);
	printf("\n\n");
	i = 0;
	char *aux;
	ls_MoverCorriente( &nombres, LS_PRIMERO );
	do {
		ls_ElemCorriente( nombres, (void**)&aux );
		i++;
		printf( "%s\n", aux );
	} while ( ls_MoverCorriente( &nombres, LS_SIGUIENTE ) );
	printf("\n\n");
	printf("Total de personas: %i", i);

	while ( !ls_Vacia(nombres) ) {
		ls_ElemCorriente( nombres, (void**)&aux );
		ls_BorrarCorriente(&(nombres));
	}
}

void testBuildStructData() {
	TGraph graph;
	TListaSimple films, people;
	int peopleAmount;
	parser_buildStructData( &graph, &films, &people, &peopleAmount );

	printf("fin.\n\n");

	int filmsAmount = 0;
	peopleAmount = 0;
	TNode *node, *node2;
	ls_MoverCorriente( &(graph.nodes), LS_PRIMERO );
	do {
		ls_ElemCorriente( graph.nodes, (void**)&node );
		if ( node->type == NODO_FILM ) filmsAmount++;
		else peopleAmount++;
		printf( "%i [%i]\n", node->id, node->type );
		if ( ls_MoverCorriente( &(node->nodes), LS_PRIMERO ) ) {
			do {
				ls_ElemCorriente( node->nodes, (void**)&node2 );
				printf( "   %i [%i]\n", node2->id, node2->type );
			} while ( ls_MoverCorriente( &(node->nodes), LS_SIGUIENTE ) );
		}
	} while ( ls_MoverCorriente( &(graph.nodes), LS_SIGUIENTE ) );

	printf("\n\nTotal de peliculas en grafo: %i\n", filmsAmount);
	printf("Total de personas en grafo: %i", peopleAmount);

	graph_destroy( &graph );

	printf("\n\n");
	regPer *reg;
	ls_MoverCorriente( &people, LS_PRIMERO );
	do {
		ls_ElemCorriente( people, (void**)&reg );
		printf( "%s   type=%i\n", reg->nombre, reg->rubro );
	} while ( ls_MoverCorriente( &people, LS_SIGUIENTE ) );

	while ( !ls_Vacia(films) ) {
		ls_BorrarCorriente(&(films));
	}
	while ( !ls_Vacia(people) ) {
		ls_BorrarCorriente(&(people));
	}
}

void testMatrix() {
	M_CREATE("/home/dela/Escritorio/matrix.dat", sizeof(regMat), 5 );

	//Escribo:
	regMat reg;
	reg.idPer = 1;
	reg.idPel = 4;
	reg.dist = 2;
	mHandler *fd = M_OPEN( "/home/dela/Escritorio/matrix.dat", READ_WRITE );
	M_WRITE( fd, 1, 0, &reg );

	//Leo:
	reg.idPer = 1;
	reg.idPel = 1;
	reg.dist = 1;
	M_READ( fd, 2, 0, &reg );
	M_CLOSE( fd );

	printf( "Per=%i Film=%i Dist=%i", reg.idPer = 1, reg.idPel = 4, reg.dist = 2 );
}

void testPreprocessor( char *fileName ) {
	TGraph graph;
	ls_Crear( &(graph.nodes) );
	//creacion de nodos:
	TNode *p0 = malloc( sizeof(TNode) );
	ls_Crear( &(p0->ids) );
	ls_Crear( &(p0->nodes) );
	p0->id = 0;
	p0->type = NODO_PERSON;
	TNode *p1 = malloc( sizeof(TNode) );
	ls_Crear( &(p1->ids) );
	ls_Crear( &(p1->nodes) );
	p1->id = 1;
	p1->type = NODO_PERSON;
	TNode *p2 = malloc( sizeof(TNode) );
	ls_Crear( &(p2->ids) );
	ls_Crear( &(p2->nodes) );
	p2->id = 2;
	p2->type = NODO_PERSON;
	TNode *p3 = malloc( sizeof(TNode) );
	ls_Crear( &(p3->ids) );
	ls_Crear( &(p3->nodes) );
	p3->id = 3;
	p3->type = NODO_PERSON;
	TNode *p4 = malloc( sizeof(TNode) );
	ls_Crear( &(p4->ids) );
	ls_Crear( &(p4->nodes) );
	p4->id = 4;
	p4->type = NODO_PERSON;

	TNode *f0 = malloc( sizeof(TNode) );
	ls_Crear( &(f0->ids) );
	ls_Crear( &(f0->nodes) );
	f0->id = 0;
	f0->type = NODO_FILM;
	TNode *f1 = malloc( sizeof(TNode) );
	ls_Crear( &(f1->ids) );
	ls_Crear( &(f1->nodes) );
	f1->id = 1;
	f1->type = NODO_FILM;
	TNode *f2 = malloc( sizeof(TNode) );
	ls_Crear( &(f2->ids) );
	ls_Crear( &(f2->nodes) );
	f2->id = 2;
	f2->type = NODO_FILM;

	//Agrego al grafo:
	ls_Insertar( &(graph.nodes), LS_PRIMERO, p0 );
	ls_Insertar( &(graph.nodes), LS_PRIMERO, p1 );
	ls_Insertar( &(graph.nodes), LS_PRIMERO, p2 );
	ls_Insertar( &(graph.nodes), LS_PRIMERO, p3 );
	ls_Insertar( &(graph.nodes), LS_PRIMERO, p4 );

	ls_Insertar( &(graph.nodes), LS_PRIMERO, f0 );
	ls_Insertar( &(graph.nodes), LS_PRIMERO, f1 );
	ls_Insertar( &(graph.nodes), LS_PRIMERO, f2 );

	//Agrego relaciones:
	ls_Insertar( &(p0->nodes), LS_PRIMERO, f0 );
	ls_Insertar( &(p1->nodes), LS_PRIMERO, f0 );
	ls_Insertar( &(p1->nodes), LS_PRIMERO, f1 );
	ls_Insertar( &(p2->nodes), LS_PRIMERO, f1 );
	ls_Insertar( &(p3->nodes), LS_PRIMERO, f0 );
	ls_Insertar( &(p3->nodes), LS_PRIMERO, f2 );
	ls_Insertar( &(p4->nodes), LS_PRIMERO, f2 );

	ls_Insertar( &(f0->nodes), LS_PRIMERO, p0 );
	ls_Insertar( &(f0->nodes), LS_PRIMERO, p1 );
	ls_Insertar( &(f0->nodes), LS_PRIMERO, p3 );
	ls_Insertar( &(f1->nodes), LS_PRIMERO, p1 );
	ls_Insertar( &(f1->nodes), LS_PRIMERO, p2 );
	ls_Insertar( &(f2->nodes), LS_PRIMERO, p3 );
	ls_Insertar( &(f2->nodes), LS_PRIMERO, p4 );

	//Genero el archivo:
	preprocessor_generateMatrix( &graph, fileName, 4 );

	//libero:
	graph_destroy( &graph );
}

void printMatrix( char *fileName, int maxId ) {
	mHandler *fd = M_OPEN( fileName, READ_WRITE );
	regMat reg;

	int fila;
	int col;
	for ( fila = 1; fila <= maxId; fila++ ) {
		for ( col = 0; col < fila; col++ ) {
			M_READ( fd, fila, col, &reg );
			printf( "[p=%i,f=%i,d=%i]\t", reg.idPer, reg.idPel, reg.dist );
		}
		printf( "\n" );
	}

	M_CLOSE( fd );
}

void testPreprocessor2( char *fileName ) {
	TGraph graph;
	TListaSimple films, people;
	int peopleAmount;

	//Construyo grafo:
	parser_buildStructData( &graph, &films, &people, &peopleAmount );

	peopleAmount--;
	printf("Max Id:%i\n", peopleAmount);

	printf("Generando archivos de peliculas y personas\n");
	preprocessor_generateFiles(&films, &people, "/media/Compartido/file");
	printf("Generación de archivos finalizada\n");
	//Genero el archivo:
	preprocessor_generateMatrix( &graph, fileName, peopleAmount );

	//libero:
	graph_destroy( &graph );

	//imprimo:
	//printMatrix( fileName, peopleAmount );
}

void printRowDistances( char *fileName, int id ) {
	mHandler *fd = M_OPEN( fileName, READ_WRITE );
	regMat reg;

	int col;
	for ( col = 0; col < id; col++ ) {
		M_READ( fd, id, col, &reg );
		printf( "%i\n", reg.dist );
	}

	M_CLOSE( fd );
}

void testMatrixWriteSpeed( char *fileName, int maxId ) {
	M_CREATE( fileName, sizeof(regMat), maxId );
	mHandler *fd = M_OPEN( fileName, READ_WRITE );

	regMat reg;
	reg.dist = 0;
	reg.idPel = 0;
	reg.idPer = 0;

	time_t inicio, seconds;

	int fila;
	int col;
	for ( fila = maxId; fila >= 1; fila-- ) {
		inicio = time (NULL);
		printf("Escribiendo fila=%i", fila);
		for ( col = 0; col < fila; col++ ) {
			M_WRITE( fd, fila, col, &reg );
		}
		seconds = time (NULL); seconds = seconds - inicio;
		printf(" [Time=%2lu]\n", seconds);
	}

	M_CLOSE( fd );
}

void testAll() {
	//parserTest();

	//testListAux();

	//testBuildStructData();

	//testMatrix();

	//testPreprocessor( "/home/maqui01/matrix.dat" );

	//printMatrix( "/home/maqui01/matrix.dat", 4 );

	//testPreprocessor2( "/home/maqui01/matrix.dat" );

	//printRowDistances( "/media/Compartido/matrix.dat", 1419 );

	//testMatrixWriteSpeed( "/media/Compartido/matrixTest.dat", 20000 );

	//testPreprocessor2( "/media/Compartido/matrix.dat" );

	//testConsultarPorGrados( "/media/Compartido/matrix.dat", "/media/Compartido/files_person", "/media/Compartido/files_films", 0, 2 );

	//testConsultarPorPersona( "/home/maqui01/matrix.dat", "/home/maqui01/files_person", "/home/maqui01/files_films", 0, 13 );
}

void preprocessor( char *fileName ) {
	TGraph graph;
	TListaSimple films, people;
	int peopleAmount;

	//Construyo grafo:
	parser_buildStructData( &graph, &films, &people, &peopleAmount );

	peopleAmount--;
	printf("Max Id:%i\n", peopleAmount);

	printf("Generando archivos de peliculas y personas\n");
	preprocessor_generateFiles(&films, &people, "/media/Compartido/file");
	printf("Generación de archivos finalizada\n");
	//Genero el archivo:
	preprocessor_generateMatrix( &graph, fileName, peopleAmount );

	//libero:
	graph_destroy( &graph );
	ls_Vaciar(&films);
	ls_Vaciar(&people);
}

/**
 *
 */
int main(int argc, char *argv[]) { //TODO ya no es el Main

	preprocessor( "/media/Compartido/matrix.dat" );

	return 0;
}
